#pragma once // 防止头文件被重复包含

#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <random>
#include <chrono>
#include <jsoncpp/json/json.h>
#include <mylogs/mylog.hpp>

namespace myrpc{
    // 使用inline定义全局日志器变量
    inline mylog::Logger::ptr server_logger = nullptr;
    inline mylog::Logger::ptr client_logger = nullptr;
    inline mylog::Logger::ptr root_logger = nullptr;
    // 实现全局日志初始化函数
    inline void initLoggers(){
        std::string pattern = "[%p][%t][%c][%f:%l] %m%n";
        mylog::loglevel::value level = mylog::loglevel::value::ERROR;
        // 1. 创建服务端全局日志器
        { 
            const std::string server_logger_name = "server_logger";
            std::unique_ptr<mylog::LoggerBuilder> serverbuilder(new mylog::GlobalLoggerBuilder());
            serverbuilder->BuildLoggerName(server_logger_name);
            serverbuilder->BuildLoggerType(mylog::LoggerType::SYNC_LOGGER);
            serverbuilder->BuildFormatter(pattern);
            serverbuilder->BuildLoggerLevel(level);
            serverbuilder->Build();
            // 创建完成后，再去安全地获取它
            server_logger = mylog::getlogger(server_logger_name);
        }

        // 2. 创建客户端全局日志器
        {
            const std::string client_logger_name = "client_logger";
            std::unique_ptr<mylog::LoggerBuilder> clientbuilder(new mylog::GlobalLoggerBuilder());
            clientbuilder->BuildLoggerName(client_logger_name);
            clientbuilder->BuildLoggerType(mylog::LoggerType::SYNC_LOGGER);
            clientbuilder->BuildFormatter(pattern);
            clientbuilder->BuildLoggerLevel(level);
            clientbuilder->Build();
            // 创建完成后，再去安全地获取它
            client_logger = mylog::getlogger(client_logger_name);
        }

        // 3. 创建root全局日志器
        {
            const std::string root_logger_name = "root_logger";
            std::unique_ptr<mylog::LoggerBuilder> rootbuilder(new mylog::GlobalLoggerBuilder());
            rootbuilder->BuildLoggerName(root_logger_name);
            rootbuilder->BuildLoggerType(mylog::LoggerType::SYNC_LOGGER);
            rootbuilder->BuildFormatter(pattern);
            rootbuilder->BuildLoggerLevel(level);
            rootbuilder->Build();
            // 创建完成后，再去安全地获取它
            root_logger = mylog::getlogger(root_logger_name);
        }
    }

    // Json序列化和反序列化工具类
    class JsonUtil{
    public:
        static bool serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 先实例化一个工厂类对象
            Json::StreamWriterBuilder swb;
            // 禁用 Unicode 转义，以便直接输出UTF-8字符（如汉字）
            swb["emitUTF8"] = true;
            // 通过工厂类对象来实例化派生类序列化对象
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

            int ret = sw->write(val, &ss);
            if (ret != 0){
                root_logger->ERROR("Json 序列化失败!");
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool unserialize(const std::string &body, Json::Value &val)
        {
            std::string errs;
            // 先实例化工厂类对象
            Json::CharReaderBuilder crb;
            // 通过工厂类对象来实现化反序列化派生类对象
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false){
                root_logger->ERROR("JSON 反序列化失败: %s", errs.c_str());
                return false;
            }
            return true;
        }
    };

    // 生成唯一标识字符串ID的工具类
    class UuId{
    public:
        static std::string uuId(){
            std::stringstream ss;
            // 构造一个真随机数对象用来生成种子
            std::random_device rd;
            // 用真随机数种子构建伪随机数对象
            std::mt19937 generator(rd());
            // 构造限定数据范围分布器对象
            std::uniform_int_distribution<int> distribution(0, 255);
            // 随即部分——生成八个随机数 按照特定格式组织成为16进制数字字符的字符串
            for (int i = 0; i < 8; i++){
                if (i == 4 || i == 6){
                    ss << "-";
                }
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";

            // 序列号部分——定义一个八字节序号 逐个字节组织成为16进制数字字符的字符串
            static std::atomic<size_t> seq = 1;  // 设置为静态的原子类型 程序的整个生命周期内获取到的都会是同一个seq
            size_t cur = seq.fetch_add(1);       // fetch_add函数每次获取seq值并加一后返回
            for (int i = 7; i >= 0; i--){
                if (i == 5){
                    ss << "-";
                }
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
            }
            return ss.str();
        }
    };
}
